﻿using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Devonline.Core;
using Microsoft.AspNetCore.Identity;

namespace Devonline.Identity
{
    /// <summary>
    /// 用户 字符串类型的默认实现
    /// </summary>
    [Table("user"), DisplayName("用户")]
    public class User : User<string>
    {
        /// <summary>
        /// 用户级别
        /// </summary>
        public virtual Level Level { get; set; }
    }

    /// <summary>
    /// 用户, 字符串类型的默认实现
    /// </summary>
    [Table("user"), DisplayName("用户")]
    public class User<TKey> : IdentityUser<TKey>, IIdentity<TKey> where TKey : IEquatable<TKey>, IConvertible
    {
        public User()
        {
            Id = KeyGenerator.GetKey<TKey>();
            RowVersion = Id;
            SecurityStamp = Id.ToString();
        }

        #region base fields from IEntitySet<string>
        /// <summary>
        /// 数据主键
        /// </summary>
        [Column("id"), DisplayName("编号"), DatabaseGenerated(DatabaseGeneratedOption.None), Key, MaxLength(36), PersonalData, Excel]
        public override TKey Id { get; set; }
        /// <summary>
        /// 行版本号
        /// </summary>
        [Column("row_version"), DisplayName("行版本号"), ConcurrencyCheck]
        public virtual TKey RowVersion { get; set; }
        /// <summary>
        /// 数据状态
        /// </summary>
        [Column("state", TypeName = "VARCHAR(16)"), DisplayName("数据状态"), DefaultValue(DataState.Available), Excel]
        public virtual DataState State { get; set; }
        /// <summary>
        /// 创建时间
        /// </summary>
        [Column("created_on"), DisplayName("创建时间"), Excel]
        public virtual DateTime? CreatedOn { get; set; }
        /// <summary>
        /// 创建人
        /// </summary>
        [Column("created_by"), DisplayName("创建人"), MaxLength(36), Excel]
        public virtual string CreatedBy { get; set; }
        /// <summary>
        /// 更新时间
        /// </summary>
        [Column("updated_on"), DisplayName("更新时间"), Excel]
        public virtual DateTime? UpdatedOn { get; set; }
        /// <summary>
        /// 更新人
        /// </summary>
        [Column("updated_by"), DisplayName("更新人"), MaxLength(36), Excel]
        public virtual string UpdatedBy { get; set; }
        /// <summary>
        /// 备注说明
        /// </summary>
        [Column("description"), DisplayName("备注说明"), MaxLength(256), Excel]
        public virtual string Description { get; set; }
        #endregion

        #region self fields
        /// <summary>
        /// 名称
        /// </summary>
        [ProtectedPersonalData]
        [Column("name"), Required, MaxLength(256), DisplayName("名称")]
        public virtual string Name { get; set; }
        /// <summary>
        /// 昵称
        /// </summary>
        [Column("alias"), MaxLength(36), DisplayName("昵称")]
        public virtual string Alias { get; set; }
        /// <summary>
        /// 头像
        /// </summary>
        [Column("image"), MaxLength(128), DisplayName("头像")]
        public virtual string Image { get; set; }
        /// <summary>
        /// 身份类型
        /// </summary>
        [Column("type", TypeName = "VARCHAR(16)"), DisplayName("身份类型"), DefaultValue(IdentityType.Internal), Excel]
        public virtual IdentityType Type { get; set; }
        /// <summary>
        /// 认证方式 AuthType 枚举类型的值
        /// </summary>
        [Column("auth_type", TypeName = "VARCHAR(16)"), DisplayName("认证方式"), DefaultValue(AuthType.Password), Excel]
        public virtual AuthType AuthType { get; set; }
        /// <summary>
        /// 授权账户编号, 如: 微信的 OpenID
        /// </summary>
        [Column("auth_id"), DisplayName("授权编号"), MaxLength(36), Excel]
        public virtual string AuthId { get; set; }
        /// <summary>
        /// 用户级别
        /// </summary>
        [Column("level_id"), DisplayName("用户级别"), MaxLength(36), Excel]
        public virtual TKey LevelId { get; set; }
        #endregion

        #region override base fields
        //
        // 摘要:
        //     Gets or sets the date and time, in UTC, when any user lockout ends.
        //
        // 言论：
        //     A value in the past means the user is not locked out.
        [Column("lockout_end"), DisplayName("锁定结束时间"), Excel]
        public override DateTimeOffset? LockoutEnd { get; set; }
        //
        // 摘要:
        //     Gets or sets a flag indicating if two factor authentication is enabled for this
        //     user.
        //
        // 值:
        //     True if 2fa is enabled, otherwise false.
        [PersonalData]
        [Column("two_factor_enabled"), DisplayName("双因素确认"), Excel]
        public override bool TwoFactorEnabled { get; set; }
        //
        // 摘要:
        //     Gets or sets a flag indicating if a user has confirmed their telephone address.
        //
        // 值:
        //     True if the telephone number has been confirmed, otherwise false.
        [PersonalData]
        [Column("phone_number_confirmed"), DisplayName("手机号码是否已确认"), Excel]
        public override bool PhoneNumberConfirmed { get; set; }
        /// <summary>
        /// 长字符串内容为密文, 由用户自己的密钥所加密, 适用于安全要求较高的场景
        /// </summary>
        [ProtectedPersonalData]
        [Column("phone_number"), DisplayName("手机号码"), MaxLength(256), Excel]
        public override string PhoneNumber { get; set; }
        //
        // 摘要:
        //     A random value that must change whenever a user is persisted to the store
        [Column("concurrency_stamp"), MaxLength(36), Excel]
        public override string ConcurrencyStamp { get; set; }
        //
        // 摘要:
        //     A random value that must change whenever a users credentials change (password
        //     changed, login removed)
        [Column("security_stamp"), MaxLength(36), Excel]
        public override string SecurityStamp { get; set; }
        //
        // 摘要:
        //     Gets or sets a salted and hashed representation of the password for this user.
        [Column("password_hash"), DisplayName("密码"), MaxLength(256), Excel]
        public override string PasswordHash { get; set; }
        //
        // 摘要:
        //     Gets or sets a flag indicating if a user has confirmed their email address.
        //
        // 值:
        //     True if the email address has been confirmed, otherwise false.
        [PersonalData]
        [Column("email_confirmed"), DisplayName("邮箱是否已确认"), Excel]
        public override bool EmailConfirmed { get; set; }
        //
        // 摘要:
        //     Gets or sets the normalized email address for this user.
        [ProtectedPersonalData]
        [Column("normalized_email"), DisplayName("归一邮箱"), MaxLength(256), Excel]
        public override string NormalizedEmail { get; set; }
        //
        // 摘要:
        //     Gets or sets the email address for this user.
        [ProtectedPersonalData]
        [Column("email"), DisplayName("邮箱"), MaxLength(256), Excel]
        public override string Email { get; set; }
        //
        // 摘要:
        //     Gets or sets the normalized user name for this user.
        [ProtectedPersonalData]
        [Column("normalized_user_name"), DisplayName("归一用户名"), MaxLength(256), Excel]
        public override string NormalizedUserName { get; set; }
        //
        // 摘要:
        //     Gets or sets the user name for this user.
        [ProtectedPersonalData]
        [Column("user_name"), Required, Unique, DisplayName("用户名"), MaxLength(256), Excel]
        public override string UserName { get; set; }
        //
        // 摘要:
        //     Gets or sets a flag indicating if the user could be locked out.
        //
        // 值:
        //     True if the user could be locked out, otherwise false.
        [Column("lockout_enabled"), DisplayName("是否锁定"), Excel]
        public override bool LockoutEnabled { get; set; }
        //
        // 摘要:
        //     Gets or sets the number of failed login attempts for the current user.
        [Column("access_failed_count"), DisplayName("访问失败次数"), Excel]
        public override int AccessFailedCount { get; set; }
        #endregion

        /// <summary>
        /// 创建方法
        /// </summary>
        public virtual void Create(string createdBy = null)
        {
            Id ??= KeyGenerator.GetKey<TKey>();
            RowVersion = Id;
            CreatedOn ??= DateTime.UtcNow;
            CreatedBy ??= createdBy ?? AppSettings.USER_SYSTEM;
        }

        /// <summary>
        /// 更新方法
        /// </summary>
        public virtual void Update(string updatedBy = null)
        {
            RowVersion = KeyGenerator.GetKey<TKey>();
            UpdatedOn ??= DateTime.UtcNow;
            UpdatedBy ??= updatedBy ?? AppSettings.USER_SYSTEM;
        }
    }
}
